package com.xcx.baseManger.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xcx.baseManger.client.MoniorFeignClient;
import com.xcx.baseManger.helper.User;
import com.xcx.baseManger.mapper.AclChooseModeMapper;
import com.xcx.baseManger.mapper.AclUserDeatilsMapper;
import com.xcx.baseManger.mapper.AclUserRoleMapper;
import com.xcx.baseManger.service.AclPermissionService;
import com.xcx.baseManger.service.MessageService;
import com.xcx.baseManger.until.ListUtils;
import com.xcx.commoncore.entity.aclentity.*;
import com.xcx.baseManger.mapper.AclUserMapper;
import com.xcx.baseManger.service.AclUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xcx.commoncore.request.aclrequest.userrequest.GetUserByOpenidRequest;
import com.xcx.commoncore.request.aclrequest.userrequest.UpdateUseChooseRequest;
import com.xcx.commoncore.request.aclrequest.userrequest.UpdateUseDetailsRequest;
import com.xcx.commoncore.request.aclrequest.userrequest.UpdateUseRequest;
import com.xcx.commoncore.request.logrequest.LogRequest;
import com.xcx.commoncore.request.logrequest.LoginMobileRequest;
import com.xcx.commoncore.request.logrequest.RegisterMobileRequest;
import com.xcx.commoncore.request.logrequest.RegisterRequest;
import com.xcx.commoncore.request.miniorequest.GetUserFileTypeRequest;
import com.xcx.commoncore.response.UserBaesRedis;
import com.xcx.commonuntils.returnuntls.ErrorEnum;
import com.xcx.commonuntils.returnuntls.ReturnMessage;
import com.xcx.commonuntils.returnuntls.ReturnMessageUtils;
import com.xcx.commonuntils.until.CheckNOtNullUtils;
import com.xcx.commonuntils.until.MD5;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author testjava
 * @since 2021-10-22
 */
@Service
@Primary
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AclUserServiceImpl extends ServiceImpl<AclUserMapper, AclUser> implements AclUserService {

    final private AclUserMapper aclUserMapper;
    final private RedisTemplate<String, String> redisTemplate;
    final private RedisTemplate<String, Object> redisObjectTemplate;
    final private AclUserDeatilsMapper aclUserDeatilsMapper;
    final private AclChooseModeMapper aclChooseModeMapper;
    final private ListUtils listUtils;
    final private AclUserRoleMapper aclUserRoleMapper;
    final private AclPermissionService aclPermissionService;
    final private MoniorFeignClient moniorFeignClient;
    final private MessageService messageDAO;
    /**
     * 注册用户
     *
     * @param registerVo
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public ReturnMessage<Object> register(RegisterRequest registerVo) {
        //是否有点击注册按钮进行注册
        if (StringUtils.isNotBlank(registerVo.getRegisterType().toString())) {
            //注册用户信息：1是微信注册，2是手机密码注册
            if (registerVo.getRegisterType() == 1) {
                //获取openid是否存在
                if (StringUtils.isNotBlank(registerVo.getUsername())) {
                    //判断微信用户是否已经注册
                    QueryWrapper<AclUser> aclUserWrapper = new QueryWrapper<>();
                    aclUserWrapper.eq("username", registerVo.getUsername());
                    int count = baseMapper.selectCount(aclUserWrapper);
                    if (count > 0) {
                        //返回用户已存在
                        return ReturnMessageUtils.errorWithEum(ErrorEnum.E_REGISTER_OPENID_EXIT);
                    }
                    //微信注册保存用户信息
                    AclUser aclUser = new AclUser();
                    BeanUtils.copyProperties(registerVo, aclUser);
                    aclUserMapper.insert(aclUser);

                    userInfoRedis(aclUser.getId());

                    return ReturnMessageUtils.success();


                }
                //openid未授权
                return ReturnMessageUtils.errorWithEum(ErrorEnum.E_REGISTER_OPENID_ERROR);
            } else if (registerVo.getRegisterType() == 2) {
                //使用用户名和密码注册
                if (StringUtils.isNotBlank(registerVo.getMobile())) {
                    //判断手机用户是否已经注册
                    QueryWrapper<AclUser> aclUserWrapper = new QueryWrapper<>();
                    aclUserWrapper.eq("mobile", registerVo.getMobile());
                    int count = baseMapper.selectCount(aclUserWrapper);
                    if (count > 0) {
                        //返回用户已存在
                        return ReturnMessageUtils.errorWithEum(ErrorEnum.E_REGISTER_MOBILE_EXIT);
                    }
                    //手机注册保存用户信息
                    AclUser aclUser = new AclUser();
                    BeanUtils.copyProperties(registerVo, aclUser);
                    aclUser.setPassword(MD5.encrypt(registerVo.getPassword()));
                    String s = UUID.randomUUID().toString();
                    aclUser.setUsername(s);
                    aclUserMapper.insert(aclUser);

                    userInfoRedis(aclUser.getId());


                    return ReturnMessageUtils.success();
                }
            } else {
                return ReturnMessageUtils.errorWithEum(ErrorEnum.E_REGISTER_TYPE_ERROR);
            }
        }
        return ReturnMessageUtils.errorWithEum(ErrorEnum.E_REGISTER_PARAM_ERROR);
    }

    /**
     * 用户登陆
     *
     * @param loginVo
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public ReturnMessage<Object> login(LogRequest loginVo) {
        //获取登陆类型
        if (StringUtils.isNotBlank(loginVo.getRegisterType().toString())) {
            //使用微信登陆
            if (loginVo.getRegisterType() == 1) {
                //微信登陆判断微信号openid是否存在
                QueryWrapper<AclUser> aclUserWrapper = new QueryWrapper<>();
                aclUserWrapper.and(i -> i.eq("username", loginVo.getUsername()).ne("is_disabled", 1));
                int count = baseMapper.selectCount(aclUserWrapper);
                if (count > 0) {
                    //从redis中取出用户的基本信息
                    Object o = redisObjectTemplate.opsForValue().get(loginVo.getUsername());
                    //返回缺失信息
                    return ReturnMessageUtils.success(o);
                } else {
                    return ReturnMessageUtils.errorWithEum(ErrorEnum.E_LOGIN_ERROR);
                }

            }
            //使用手机验证码登陆
            else if (loginVo.getRegisterType() == 2) {
                //判断验证码
                //获取redis验证码
                String redisCode = redisTemplate.opsForValue().get(loginVo.getMobile());
                if (!loginVo.getCode().equals(redisCode)) {
                    return ReturnMessageUtils.errorWithEum(ErrorEnum.E_UCENTER_CODE_FAIL);
                }
                //判断手机号码是否存在
                QueryWrapper<AclUser> aclUserWrapper = new QueryWrapper<>();
                aclUserWrapper.and(i -> i.eq("mobile", loginVo.getMobile()).ne("is_disabled", 1));
                AclUser aclUser = baseMapper.selectOne(aclUserWrapper);
                if (null != aclUser) {
                    //返回登陆成功
                    Object o = redisObjectTemplate.opsForValue().get(aclUser.getUsername());
                    return ReturnMessageUtils.success(o);
                } else {
                    return ReturnMessageUtils.errorWithEum(ErrorEnum.E_LOGIN_ERROR);
                }
            }

        }
        return ReturnMessageUtils.errorWithEum(ErrorEnum.E_REGISTER_PARAM_ERROR);

    }




    /**
     * 判断用户是否存在
     *
     * @param openid
     * @return
     */

    public Boolean checkUserFeign(String openid) {
        QueryWrapper<AclUser> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("username", openid);
        Integer aclUser = aclUserMapper.selectCount(userQueryWrapper);
        if (aclUser > 0) {
            return true;
        }
        return false;
    }

    /**
     * 获取人员基本，详情，择偶，角色信息
     *
     * @param request
     * @return
     */
    @Override
    public ReturnMessage<Object> getByOpenid(GetUserByOpenidRequest request) {
        //通过openid把人员的角色，服务，择偶要求，个人基本信息，详细信息返回
        QueryWrapper<AclUser> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("username", request.getUsername());
        AclUser aclUser = baseMapper.selectOne(userQueryWrapper);
        AclUser userByOpenid = aclUserMapper.getUserByOpenid(request.getUsername());
        List<AclPermission> permissionByOpenid = aclPermissionService.getPermissionByOpenid(aclUser);
        userByOpenid.setAclPermissionList(permissionByOpenid);
        //远程调用文件服务器获取人员的头像地址
        return ReturnMessageUtils.success(userByOpenid);
    }

    /**
     * 更新用户基本信息
     *
     * @param request
     * @return
     */
    @Override
    public ReturnMessage<Object> updateBaseInfo(UpdateUseRequest request) {
        //通过微信openid获取用户对象
        QueryWrapper<AclUser> wrapper = new QueryWrapper<>();
        wrapper.eq("username", request.getUsername());
        AclUser aclUser = aclUserMapper.selectOne(wrapper);
        if (null == aclUser) {
            return ReturnMessageUtils.errorWithEum(ErrorEnum.E_USER_BASE_ERROR);
        }
        //更新用户基本信息
        BeanUtils.copyProperties(request, aclUser);
        aclUserMapper.updateById(aclUser);
        //
        boolean b = CheckNOtNullUtils.checkObjAllFieldsIsNull(aclUser);
        if (b) {
            redisTemplate.delete(aclUser.getUsername());
            ReturnMessageUtils.success();
        }
        //获取空字段名称
        String[] nullPropert = CheckNOtNullUtils.getNullPropert(aclUser);
        List<String> filterNames = new ArrayList<>();
        filterNames.add("aclChooseMode");
        filterNames.add("password");
        filterNames.add("aclUserDeatils");
        filterNames.add("registerType");
        //filterNames.add("filePath");
        filterNames.add("age");
        List<String> collect = Arrays.stream(nullPropert).filter(s -> !filterNames.contains(s)
        ).collect(Collectors.toList());
        listUtils.rightPushAll(aclUser.getUsername(), collect);
        //设置过期时间
        redisObjectTemplate.expire(aclUser.getUsername(), 365, TimeUnit.DAYS);
        //listUtils.leftPop(aclUser.getUsername(),30000);
        return ReturnMessageUtils.success();

    }

    /**
     * 更新详细信息
     *
     * @param request
     * @return
     */
    @Override
    public ReturnMessage<Object> updateDetailInfo(UpdateUseDetailsRequest request) {
        //通过微信openid获取用户对象
        AclUserDeatils aclUserDeatils = aclUserDeatilsMapper.queryUserByOpid(request.getUsername());
        if (null == aclUserDeatils) {
            return ReturnMessageUtils.errorWithEum(ErrorEnum.E_USER_BASE_ERROR);
        }
        //更新详细信息
        BeanUtils.copyProperties(request, aclUserDeatils);
        aclUserDeatilsMapper.updateById(aclUserDeatils);

        return ReturnMessageUtils.success();

    }

    @Override
    public ReturnMessage<Object> updateChooseInfo(UpdateUseChooseRequest request) {

        AclChooseMode aclChooseMode = aclChooseModeMapper.queryUserByOpid(request.getUsername());
        if (null == aclChooseMode) {
            return ReturnMessageUtils.errorWithEum(ErrorEnum.E_USER_BASE_ERROR);
        }
        BeanUtils.copyProperties(request, aclChooseMode);
        aclChooseModeMapper.updateById(aclChooseMode);
        return ReturnMessageUtils.success();
    }

    /**
     * 文件服务远程跳用新增头像地址
     *
     * @param username
     * @param filePath
     */
    @Override
    public ReturnMessage<Object> updateUserFileIndex(String username, String filePath) {
        QueryWrapper<AclUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        AclUser aclUser = aclUserMapper.selectOne(queryWrapper);

        aclUser.setFilePath(filePath);
        aclUserMapper.updateById(aclUser);
        return ReturnMessageUtils.success();
    }

    /**
     * 小程序注册
     *
     * @param registerVo
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    public ReturnMessage<Object> registerMobile(RegisterMobileRequest registerVo) {
        if (StringUtils.isNotBlank(registerVo.getUsername()) || StringUtils.isNotBlank(registerVo.getMobile())
                || StringUtils.isNotBlank(registerVo.getAppid())) {
            ReturnMessageUtils.errorWithEum(ErrorEnum.E_REGISTER_OPENID_ERROR);
        }
        QueryWrapper<AclUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper.eq("username", registerVo.getUsername()).
                or()
                .eq("appid", registerVo.getAppid()));
        Integer count = aclUserMapper.selectCount(queryWrapper);
        if (count > 0) {
            return ReturnMessageUtils.errorWithEum(ErrorEnum.E_REGISTER_OPENID_EXIT);
        }
        AclUser aclUser = new AclUser();
        BeanUtils.copyProperties(registerVo, aclUser);
        aclUserMapper.insert(aclUser);

        AclUserRole aclUserRole = new AclUserRole();
        aclUserRole.setRoleId(1);
        aclUserRole.setUserId(aclUser.getId());
        aclUserRoleMapper.insert(aclUserRole);

        AclUserDeatils aclUserDeatils = new AclUserDeatils();
        aclUserDeatils.setUserId(aclUser.getId());
        aclUserDeatilsMapper.insert(aclUserDeatils);

        AclChooseMode aclChooseMode = new AclChooseMode();
        aclChooseMode.setUserId(aclUser.getId());
        aclChooseModeMapper.insert(aclChooseMode);
        saveUserToMongoDb(aclUser,aclUserRole);

        return ReturnMessageUtils.success();

    }




    /**
     *
     * 保存数据到mongodb
     * @param aclUser
     * @param aclUserRole
     */
    public void saveUserToMongoDb(AclUser aclUser,AclUserRole aclUserRole){
        User user = new User();
        user.setUserId(aclUser.getId());
        user.setUsername(aclUser.getUsername());
        user.setRoleId(aclUserRole.getRoleId());
        user.setId(ObjectId.get());
        messageDAO.saveUser(user);
    }
















    @Override
    public ReturnMessage<Object> loginWx(LoginMobileRequest loginVo) {
        if (StringUtils.isNotBlank(loginVo.getUsername())
                || StringUtils.isNotBlank(loginVo.getAppid())) {
            ReturnMessageUtils.errorWithEum(ErrorEnum.E_REGISTER_OPENID_ERROR);
        }
        //把未填写信息缓存到redis中
        QueryWrapper<AclUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", loginVo.getUsername()).eq("appid", loginVo.getAppid());

        AclUser aclUser = aclUserMapper.selectOne(queryWrapper);
        if (null == aclUser) {
            return ReturnMessageUtils.errorWithEum(ErrorEnum.E_LOGIN_ERROR);
        }

        boolean b = CheckNOtNullUtils.checkObjAllFieldsIsNull(aclUser);
        if (b) {
//            redisTemplate.delete(aclUser.getUsername());
            ReturnMessageUtils.success();
        }

        //查看基本信息中哪些未填写
        // Long size = redisTemplate.opsForList().size(aclUser.getUsername());
        List<String> range = redisTemplate.opsForList().range(aclUser.getUsername(), 0, -1);
        if (range.size() == 0) {
            //获取空字段名称
            String[] nullPropert = CheckNOtNullUtils.getNullPropert(aclUser);
            List<String> filterNames = new ArrayList<>();
            filterNames.add("aclChooseMode");
            filterNames.add("password");
            filterNames.add("aclUserDeatils");
            filterNames.add("registerType");
            //filterNames.add("filePath");
            filterNames.add("age");
            List<String> collect = Arrays.stream(nullPropert).filter(s -> !filterNames.contains(s)
            ).collect(Collectors.toList());
            listUtils.rightPushAll(aclUser.getUsername(), collect);
            //设置过期时间
            redisObjectTemplate.expire(aclUser.getUsername(), 365, TimeUnit.DAYS);
            //listUtils.leftPop(aclUser.getUsername(),30000);
            return ReturnMessageUtils.success(collect);
        }
        return ReturnMessageUtils.success(range);
    }

    @Override
    public ReturnMessage<Object> removeByMobile(String mobile) {
        QueryWrapper<AclUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mobile", mobile);
        AclUser aclUser2 = aclUserMapper.selectOne(queryWrapper);

        if (aclUser2 == null){

            ReturnMessageUtils.errorWithEum(ErrorEnum.E_REMOVE_USER);
        }
        Integer aclUserId = aclUser2.getId();
        String username = aclUser2.getUsername();
        aclUserMapper.deleteById(aclUserId);

        QueryWrapper<AclUserDeatils> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("user_id", aclUserId);
        aclUserDeatilsMapper.delete(queryWrapper1);
        QueryWrapper<AclChooseMode> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("user_id", aclUserId);
        aclChooseModeMapper.delete(queryWrapper2);

        QueryWrapper<AclUserRole> queryWrapper3 = new QueryWrapper<>();
        queryWrapper3.eq("user_id", aclUserId);
        aclUserRoleMapper.delete(queryWrapper3);

        GetUserFileTypeRequest getUserFileTypeRequest = new GetUserFileTypeRequest();
        getUserFileTypeRequest.setType(1);
        getUserFileTypeRequest.setUsername(username);
        moniorFeignClient.remove(getUserFileTypeRequest);
        return ReturnMessageUtils.success();
    }


    /**
     * 缓存用户信息
     *
     * @param userid
     */
    public void userInfoRedis(Integer userid) {
        //根据opdnid查询对应用户的数据
        AclUser aclUser = baseMapper.selectById(userid);

        UserBaesRedis userBaesRedis = new UserBaesRedis();
        BeanUtils.copyProperties(aclUser, userBaesRedis);
        //判断redis是否已保存该用户数据，如果保存则重新更新
        Object o = redisObjectTemplate.opsForValue().get(aclUser.getUsername());
        //判断基础信息缺失项目
        if (o == null) {
            //把基础信息缺失部分存在redis
            redisObjectTemplate.opsForValue().set(aclUser.getUsername(), userBaesRedis, 30, TimeUnit.DAYS);
        } else {
            //如果已存在删除原来的添加新的
            redisObjectTemplate.delete(aclUser.getUsername());
            //把基础信息缺失部分存在redis
            redisObjectTemplate.opsForValue().set(aclUser.getUsername(), userBaesRedis, 30, TimeUnit.DAYS);

        }

    }


}